#include "trackview.h"
#include <QPainter>
#include <QGraphicsSceneMouseEvent>
#include <QMouseEvent>
#include <cmath>
#include <QDebug>

TrackView::TrackView(QWidget *parent)
    : QGraphicsView(parent), m_radius(100), m_straightLength(200), m_animationSpeed(50)
{
    setRenderHint(QPainter::Antialiasing);
    setDragMode(QGraphicsView::NoDrag);
    setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
    
    m_scene = new QGraphicsScene(this);
    if(m_scene ==Q_NULLPTR){
        return ;
    }
    setScene(m_scene);
    
    m_trackItem = new QGraphicsPathItem();
    if(m_trackItem ==Q_NULLPTR){
        return ;
    }

    m_trackItem->setPen(QPen(Qt::darkGray, 3));
    m_scene->addItem(m_trackItem);
    
    m_timer = new QTimer(this);
    if(m_timer ==Q_NULLPTR){
        return ;
    }
    connect(m_timer, &QTimer::timeout, this, &TrackView::animateVehicles);
    
    updateTrackPath();
    
    m_draggedVehicle = nullptr;
    m_isDragging = false;
}

void TrackView::setRadius(qreal radius)
{
    if (radius > 0) {
        m_radius = radius;
        updateTrackPath();
    }
}

void TrackView::setStraightLength(qreal length)
{
    if (length > 0) {
        m_straightLength = length;
        updateTrackPath();
    }
}

void TrackView::addVehicle(const QColor &color, qreal size)
{
    Vehicle *vehicle = new Vehicle(m_vehicles.size(), color, size);
    m_vehicles.append(vehicle);
    m_scene->addItem(vehicle);
    
    // 均匀分布在轨道上
    qreal trackLength = getTrackLength();
    qreal spacing = trackLength / (m_vehicles.size() + 1);
    for (int i = 0; i < m_vehicles.size(); ++i) {
        m_vehicles[i]->setTrackPosition(spacing * (i + 1));
        QPointF pos = getPointOnTrack(m_vehicles[i]->trackPosition());
        m_vehicles[i]->setPos(pos - QPointF(size/2, size/2));
    }
}

void TrackView::removeVehicle(int index)
{
    if (index >= 0 && index < m_vehicles.size()) {
        Vehicle *vehicle = m_vehicles.takeAt(index);
        m_scene->removeItem(vehicle);
        delete vehicle;
    }
}

void TrackView::removeSelectedVehicle()
{
    QList<QGraphicsItem*> selected = m_scene->selectedItems();
    for (QGraphicsItem *item : selected) {
        Vehicle *vehicle = dynamic_cast<Vehicle*>(item);
        if (vehicle) {
            int index = m_vehicles.indexOf(vehicle);
            if (index != -1) {
                removeVehicle(index);
                break;
            }
        }
    }
}

Vehicle* TrackView::vehicleAt(int index) const
{
    if (index >= 0 && index < m_vehicles.size()) {
        return m_vehicles[index];
    }
    return nullptr;
}

int TrackView::vehicleCount() const
{
    return m_vehicles.size();
}

void TrackView::startAnimation()
{
    if (!m_timer->isActive()) {
        m_timer->start(50); // 20 FPS
    }
}

void TrackView::stopAnimation()
{
    m_timer->stop();
}

void TrackView::updateTrackPath()
{
    QPainterPath path;
    
    // 计算轨道路径
    qreal totalWidth = m_straightLength + 2 * m_radius;
    qreal totalHeight = 2 * m_radius;
    
    // 左半圆
    path.moveTo(m_radius, 0);
    path.arcTo(0, 0, 2 * m_radius, 2 * m_radius, 90, 180);
    
    // 下直线
    path.lineTo(m_radius + m_straightLength, 2 * m_radius);
    
    // 右半圆
    path.arcTo(m_straightLength, 0, 2 * m_radius, 2 * m_radius, 270, 180);
    
    // 上直线
    path.lineTo(m_radius, 0);
    
    m_trackItem->setPath(path);
#if 0
    QPainterPathHelper help;
    QVector<QPointF> precisePoints = help.getPreciseInterpolatedPoints(path);

    // 使用这些点
    for (const QPointF& point : precisePoints) {
        qDebug() << QString( "%1,%2;" ).arg( point.x() ).arg(  point.y() ) ;
    }
#endif

    
    // 更新小车位置
    for (Vehicle *vehicle : m_vehicles) {
        QPointF pos = getPointOnTrack(vehicle->trackPosition());
        vehicle->setPos(pos - QPointF(vehicle->size()/2, vehicle->size()/2));
    }
}

QPointF TrackView::getPointOnTrack(qreal position) const
{
    qreal trackLength = getTrackLength();
    position = fmod(position, trackLength);
    if (position < 0) position += trackLength;
    
    qreal halfCircumference = M_PI * m_radius;
    qreal straightSegment = m_straightLength;
    
    // 左半圆
    if (position < halfCircumference) {
        qreal angle = position / m_radius - M_PI/2.0;
        return QPointF(
            m_radius - m_radius * cos(angle),
            m_radius - m_radius * sin(angle)
        );
    }
    // 上直线
    else if (position < halfCircumference + straightSegment) {
        return QPointF(
            m_radius + (position - halfCircumference),
            0
        );
    }
    // 右半圆
    else if (position < halfCircumference * 2 + straightSegment) {
        qreal angle = (position - halfCircumference - straightSegment) / m_radius - M_PI/2.0;
        return QPointF(
            m_radius + m_straightLength + m_radius * cos(angle),
            m_radius + m_radius * sin(angle)
        );
    }
    // 下直线
    else {
        return QPointF(
            m_radius + m_straightLength - (position - halfCircumference * 2 - straightSegment),
            2 * m_radius
        );
    }
}

qreal TrackView::getTrackLength() const
{
    return 2 * M_PI * m_radius + 2 * m_straightLength;
}

qreal TrackView::findClosestPosition(const QPointF &point) const
{
    qreal minDistance = 1e9;
    qreal closestPos = 0;
    
    // 采样轨道上的点来找到最近位置
    const int samples = 1000;
    for (int i = 0; i < samples; ++i) {
        qreal pos = (getTrackLength() * i) / samples;
        QPointF trackPoint = getPointOnTrack(pos);
        qreal distance = QLineF(trackPoint, point).length();
        
        if (distance < minDistance) {
            minDistance = distance;
            closestPos = pos;
        }
    }
    
    return closestPos;
}

void TrackView::drawBackground(QPainter *painter, const QRectF &rect)
{
    QGraphicsView::drawBackground(painter, rect);
    
    // 绘制网格背景
    painter->setPen(QPen(Qt::lightGray, 0.5));
    qreal gridSize = 20;
    
    for (qreal x = rect.left() - fmod(rect.left(), gridSize); x < rect.right(); x += gridSize) {
        painter->drawLine(QPointF(x, rect.top()), QPointF(x, rect.bottom()));
    }
    
    for (qreal y = rect.top() - fmod(rect.top(), gridSize); y < rect.bottom(); y += gridSize) {
        painter->drawLine(QPointF(rect.left(), y), QPointF(rect.right(), y));
    }
}

void TrackView::resizeEvent(QResizeEvent *event)
{
    QGraphicsView::resizeEvent(event);
    
    // 调整场景大小以适应视图
    QRectF rect = m_trackItem->path().boundingRect();
    rect.adjust(-50, -50, 50, 50);
    m_scene->setSceneRect(rect);
    
    // 自动缩放以适应视图
    fitInView(m_scene->sceneRect(), Qt::KeepAspectRatio);
}

void TrackView::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        QPointF scenePos = mapToScene(event->pos());
        Vehicle *vehicle = dynamic_cast<Vehicle*>(itemAt(event->pos()));
        
        if (vehicle) {
            m_draggedVehicle = vehicle;
            m_dragOffset = scenePos - vehicle->pos();
            m_isDragging = true;
            vehicle->setSelected(true);
        }
    }
    
    QGraphicsView::mousePressEvent(event);
}

void TrackView::mouseMoveEvent(QMouseEvent *event)
{
    if (m_isDragging && m_draggedVehicle) {
        QPointF scenePos = mapToScene(event->pos());
        QPointF newPos = scenePos - m_dragOffset;
        
        // 找到轨道上最近的点
        qreal closestPos = findClosestPosition(newPos + QPointF(m_draggedVehicle->size()/2, m_draggedVehicle->size()/2));
        QPointF trackPoint = getPointOnTrack(closestPos);
        
        // 更新小车位置
        m_draggedVehicle->setTrackPosition(closestPos);
        m_draggedVehicle->setPos(trackPoint - QPointF(m_draggedVehicle->size()/2, m_draggedVehicle->size()/2));
        
        emit vehicleMoved(m_draggedVehicle, trackPoint);
    }
    
    QGraphicsView::mouseMoveEvent(event);
}

void TrackView::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton && m_isDragging) {
        m_isDragging = false;
        m_draggedVehicle = nullptr;
    }
    
    QGraphicsView::mouseReleaseEvent(event);
}

void TrackView::animateVehicles()
{
    static qreal delta = 0;
    delta += 0.01 * m_animationSpeed;
    
    for (Vehicle *vehicle : m_vehicles) {
        qreal newPos = vehicle->trackPosition() + delta;
        vehicle->setTrackPosition(newPos);
        
        QPointF pos = getPointOnTrack(newPos);
        vehicle->setPos(pos - QPointF(vehicle->size()/2, vehicle->size()/2));
    }
}
